package meow

/** つぶやきやタイムライン全般をたばねるサービス  */
class TwitterService {
  static final def MAX_RESULT = Utils.MAX_RESULT
  boolean transactional = true

  /** タイムラインの取得  */
  def findTimelines(page, username) {
    def timelines = Timeline.withCriteria {
      eq 'ownername', username
      maxResults MAX_RESULT
      firstResult(page * MAX_RESULT)
      order 'createDate', 'desc'
    }
    def nextPage = timelines.size() < MAX_RESULT ? 0 : ++page
    [username: username, timelines: timelines, page: nextPage]
  }

  /** つぶやきの取得  */
  def findStatuses(page, username) {
    def statuses = Status.withCriteria {
      account { eq 'username', username }
      maxResults MAX_RESULT
      firstResult(page * MAX_RESULT)
      order 'dateCreated', 'desc'
    }
    def nextPage = statuses.size() < MAX_RESULT ? 0 : ++page
    def user = Account.findByUsername(username)
    [statuses: statuses, user: user, page: nextPage]
  }

  /** リプライメッセージの取得  */
  def findReplies(page, username) {
    def replies = Reply.withCriteria {
      eq 'ownername', username
      maxResults MAX_RESULT
      firstResult(page * MAX_RESULT)
      order 'createDate', 'desc'
    }
    def nextPage = replies.size() < MAX_RESULT ? 0 : ++page
    def user = Account.findByUsername(username)
    [replies: replies, user: user, page: nextPage]
  }

  /** つぶやく  */
  def updateStatus(status) {
    // ステータス（発言）を保存
    status.save()
    // 自分のタイムラインは同一トランザクション内で処理する
    new Timeline(ownername: status.account.username,
                 status: status, statusOwner: status.account,
                 createDate: status.dateCreated).save(flush: true)
    // リプライも同一トランザクション内で処理する
    status.replies().each {address ->
      // 実在確認しとくか...
      if (Account.findByUsername(address)) {
        log.info "${address} にメッセージを送るよ"
        new Reply(ownername: address,
                  status: status, statusOwner: status.account,
                  createDate: status.dateCreated).save()
      }
    }
    // フォロアーへの通知は非同期で行う
    sendJMSMessage("queue.timeline", status)
  }

  /** フォローする
   * @param ownername フォローする人
   * @param targetname フォローされる人
   */
  def follow(ownername, targetname) {
    def owner = Account.findByUsername(ownername)
    def target = Account.findByUsername(targetname)
    def followers = new Followers(owner: owner, target: target).save()
    // お気に入り登録した人のタイムラインを回収する
    sendJMSMessage("queue.follow", followers)
  }

  /** フォローをやめる
   * @param ownername フォローする人
   * @param targetname フォローされる人
   */
  def unfollow(ownername, targetname) {
    def followers = Followers.withCriteria {
      owner { eq 'username', ownername }
      target { eq 'username', targetname }
    }
    if (!followers.isEmpty()) {
      // ホントは一括処理したいんだけどHQLがわからんので，妥協案で非同期にした
      sendJMSMessage("queue.unfollow", followers[0])
      // この組合せが複数あるのはあり得ないので，明示的に１つとして扱う
      followers[0].delete()
    }
  }


}
